/**
 * 浮点数精度处理工具函数 - UniApp版本
 * 解决JavaScript浮点数运算精度问题
 */

/**
 * 获取数字的小数位数
 * @param {number} num 数字
 * @returns {number} 小数位数
 */
function getDecimalPlaces(num) {
  const str = num.toString();
  if (str.indexOf(".") !== -1) {
    return str.split(".")[1].length;
  }
  return 0;
}

/**
 * 将数字转换为整数，用于精确计算
 * @param {number} num 数字
 * @returns {object} 转换后的整数和放大倍数
 */
function toInteger(num) {
  const decimalPlaces = getDecimalPlaces(num);
  const factor = Math.pow(10, decimalPlaces);
  return {
    value: Math.round(num * factor),
    factor: factor,
  };
}

/**
 * 精确加法
 * @param {number|string} a 加数
 * @param {number|string} b 被加数
 * @param {number} precision 保留小数位数，默认2位
 * @returns {number} 精确的加法结果
 */
export function add(a, b, precision = 2) {
  const numA = Number(a);
  const numB = Number(b);

  if (isNaN(numA) || isNaN(numB)) {
    throw new Error("参数必须是有效的数字");
  }

  const maxDecimalPlaces = Math.max(
    getDecimalPlaces(numA),
    getDecimalPlaces(numB)
  );
  const factor = Math.pow(10, maxDecimalPlaces);

  const result =
    (Math.round(numA * factor) + Math.round(numB * factor)) / factor;
  return Number(result.toFixed(precision));
}

/**
 * 精确减法
 * @param {number|string} a 被减数
 * @param {number|string} b 减数
 * @param {number} precision 保留小数位数，默认2位
 * @returns {number} 精确的减法结果
 */
export function subtract(a, b, precision = 2) {
  const numA = Number(a);
  const numB = Number(b);

  if (isNaN(numA) || isNaN(numB)) {
    throw new Error("参数必须是有效的数字");
  }

  const maxDecimalPlaces = Math.max(
    getDecimalPlaces(numA),
    getDecimalPlaces(numB)
  );
  const factor = Math.pow(10, maxDecimalPlaces);

  const result =
    (Math.round(numA * factor) - Math.round(numB * factor)) / factor;
  return Number(result.toFixed(precision));
}

/**
 * 精确乘法
 * @param {number|string} a 乘数
 * @param {number|string} b 被乘数
 * @param {number} precision 保留小数位数，默认2位
 * @returns {number} 精确的乘法结果
 */
export function multiply(a, b, precision = 2) {
  const numA = Number(a);
  const numB = Number(b);

  if (isNaN(numA) || isNaN(numB)) {
    throw new Error("参数必须是有效的数字");
  }

  const intA = toInteger(numA);
  const intB = toInteger(numB);

  const result = (intA.value * intB.value) / (intA.factor * intB.factor);
  return Number(result.toFixed(precision));
}

/**
 * 精确除法
 * @param {number|string} a 被除数
 * @param {number|string} b 除数
 * @param {number} precision 保留小数位数，默认2位
 * @returns {number} 精确的除法结果
 */
export function divide(a, b, precision = 2) {
  const numA = Number(a);
  const numB = Number(b);

  if (isNaN(numA) || isNaN(numB)) {
    throw new Error("参数必须是有效的数字");
  }

  if (numB === 0) {
    throw new Error("除数不能为零");
  }

  const intA = toInteger(numA);
  const intB = toInteger(numB);

  const result = (intA.value / intB.value) * (intB.factor / intA.factor);
  return Number(result.toFixed(precision));
}

/**
 * 格式化金额显示
 * @param {number|string} amount 金额
 * @param {number} precision 小数位数，默认2位
 * @param {boolean} showCurrency 是否显示货币符号，默认false
 * @returns {string} 格式化后的金额字符串
 */
export function formatAmount(amount, precision = 2, showCurrency = false) {
  const num = Number(amount);

  if (isNaN(num)) {
    return showCurrency ? "¥0.00" : "0.00";
  }

  const formatted = num.toFixed(precision);
  return showCurrency ? `¥${formatted}` : formatted;
}

/**
 * 安全的数字转换
 * @param {any} value 要转换的值
 * @param {number} defaultValue 默认值，默认为0
 * @returns {number} 转换后的数字
 */
export function safeNumber(value, defaultValue = 0) {
  const num = Number(value);
  return isNaN(num) ? defaultValue : num;
}

/**
 * 计算商品总价（数量 × 单价）
 * @param {number|string} quantity 数量
 * @param {number|string} price 单价
 * @param {number} precision 保留小数位数，默认2位
 * @returns {number} 总价
 */
export function calculateTotalPrice(quantity, price, precision = 2) {
  return multiply(quantity, price, precision);
}

/**
 * 计算订单总金额
 * @param {Array} items 订单项数组，每项包含quantity和price
 * @param {number} precision 保留小数位数，默认2位
 * @returns {number} 订单总金额
 */
export function calculateOrderTotal(items, precision = 2) {
  return items.reduce((total, item) => {
    const itemTotal = multiply(
      item.quantity || item.number,
      item.price || item.pPrice,
      precision
    );
    return add(total, itemTotal, precision);
  }, 0);
}

/**
 * 验证是否为有效的金额
 * @param {any} value 要验证的值
 * @param {boolean} allowZero 是否允许为0，默认true
 * @returns {boolean} 验证结果
 */
export function isValidAmount(value, allowZero = true) {
  const num = Number(value);

  if (isNaN(num)) {
    return false;
  }

  if (!allowZero && num === 0) {
    return false;
  }

  return num >= 0;
}

/**
 * 比较两个数字是否相等（考虑精度问题）
 * @param {number|string} a 数字a
 * @param {number|string} b 数字b
 * @param {number} precision 精度，默认2位小数
 * @returns {boolean} 是否相等
 */
export function isEqual(a, b, precision = 2) {
  const numA = Number(a);
  const numB = Number(b);

  if (isNaN(numA) || isNaN(numB)) {
    return false;
  }

  const factor = Math.pow(10, precision);
  return Math.round(numA * factor) === Math.round(numB * factor);
}

// 默认导出所有函数
export default {
  add,
  subtract,
  multiply,
  divide,
  formatAmount,
  safeNumber,
  calculateTotalPrice,
  calculateOrderTotal,
  isValidAmount,
  isEqual,
};
